#include "Arith.h"

#include <math.h>

Arith::Arith(Expr *_expr1, Expr *_expr2, Token *_tok)
    :leftExpr(_expr1), rightExpr(_expr2), Expr(_tok)
{
    if (token->Tag() == '^')
    {
        type = FLT;
    }
    else if (leftExpr->Type() == INT && rightExpr->Type() == INT)
    {
        type = INT;
    }
    else if (token->Tag() == '>' || token->Tag() == '<' || token->Tag() == '=' ||
             token->Tag() == LE || token->Tag() == NE || token->Tag() == GE)
    {
        type = INT;
    }
    else
    {
        type = FLT;
    }
}


Arith::~Arith(void)
{
    delete rightExpr;
    delete leftExpr;
}

int Arith::DoEvalInt()
{
    int lnVal = leftExpr->EvalInt();
    int rnVal = rightExpr->EvalInt();
    float lfVal = leftExpr->EvalFlt();
    float rfVal = rightExpr->EvalFlt();
    
    switch (token->Tag())
    {
    case '+':
        return lnVal + rnVal;
    case '-':
        return lnVal - rnVal;
    case '*':
        return lnVal * rnVal;
    case '/':
        return lnVal / rnVal;
    case '>':
        return lfVal > rfVal;
    case '<':
        return lfVal < rfVal;
    case '=':
        return EqualFlt(lfVal, rfVal);
    case LE:
        return lfVal <= rfVal;
    case NE:
        return !EqualFlt(lfVal, rfVal);
    case GE:
        return lfVal >= rfVal;
    default:
        assert(0);
        break;
    }

    return -1;
}

float Arith::DoEvalFlt()
{
    int lnVal = leftExpr->EvalInt();
    int rnVal = rightExpr->EvalInt();
    float lfVal = leftExpr->EvalFlt();
    float rfVal = rightExpr->EvalFlt();

    switch (token->Tag())
    {
    case '+':
        return lfVal + rfVal;
    case '-':
        return lfVal - rfVal;
    case '*':
        return lfVal * rfVal;
    case '/':
        return lfVal / rfVal;
    case '^':
        return pow(lfVal, rfVal);
    default:
        assert(0);
        break;
    }

    return -1;;
}
